# -*- coding: utf-8 -*-
# Created by shu2015626 on 2019-10-16
"""
使用subprocess的方式，调用python文件
推荐！！
"""
import re
import logging
import subprocess
from celery import shared_task

from apps.CeleryTaskBase import CeleryTaskBase

logger = logging.getLogger("tasks")


@shared_task(bind=True, name="common.subprocess_common_task", base=CeleryTaskBase, max_retries=3,
             default_retry_delay=10 * 60, retry_kwargs={'max_retries': 3, 'countdown': 10 * 60})
def subprocess_common_task(self, cmd: str):
    """
    使用subprocess执行脚本
    :param self:  绑定的celery task的实例
    :param cmd:  待执行的命令字符串。 最好都是全路径的
    :return:
    """
    res = {}

    if isinstance(cmd, list):
        cmd = " ".join(cmd)

    # check=True, 如果subprocess.run抛异常，会直接向外抛subprocess的返回值不为0的异常，不会记录执行文件内部的报错
    # check=False, 如果subprocess.run返回值不为0，不会抛异常，而是把错误记在stderr中
    p_result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, check=False)

    # 获取执行文件的异常，并继续向上抛出异常，给apps.CeleryTaskBase的on_failure回调函数
    if p_result.returncode != 0:
        try:
            error = p_result.stderr.decode('utf-8')
        except UnicodeDecodeError as e:
            try:
                error = p_result.stderr.decode('gb18030')
            except UnicodeDecodeError as e:
                error = p_result.stderr
        raise Exception(error)

    try:
        out = p_result.stdout.decode('utf-8')
    except UnicodeDecodeError as e:
        try:
            out = p_result.stdout.decode('gb18030')
        except UnicodeDecodeError as e:
            out = p_result.stdout

    # 获取执行的文件名称
    operate_file = re.split(r"[/\\]", cmd.strip())[-1]
    if operate_file and "." in operate_file:
        self.request.operate_file = operate_file

    res['result'] = out
    res['hostname'] = self.request.hostname
    res['cmd'] = cmd
    res['task_name'] = self.request.task
    res['task_id'] = self.request.id
    # print('res: ', res)
    # print("self.request: ", self.request)
    # print("dir(self.request): ", dir(self.request))
    return res
